home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / indent / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-06  |  12.7 KB  |  522 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * Copyright (c) 1976 Board of Trustees of the University of Illinois.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that this notice is preserved and that due credit is given
  8.  * to the University of California at Berkeley and the University of
  9.  * Illinois at Urbana.  The name of either University may not be used
  10.  * to endorse or promote products derived from this software without
  11.  * specific prior written permission. This software is provided
  12.  * ``as is'' without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char sccsid[] = "@(#)io.c    5.6 (Berkeley) 3/22/88";
  17. #endif /* not lint */
  18.  
  19. /*
  20.  * FILE NAME:
  21.  *    io.c
  22.  * PURPOSE:
  23.  *    Contains routines to handle i/o related stuff for indent.
  24.  * GLOBALS:
  25.  *    None
  26.  * FUNCTIONS:
  27.  *    dump_line
  28.  *    fill_buffer
  29.  *    pad_output
  30.  *    count_spaces
  31.  *    eqin
  32.  *    cmp
  33.  *
  34.  */
  35. /*-
  36.  *
  37.  *              Copyright (C) 1976
  38.  *                by the
  39.  *              Board of Trustees
  40.  *                of the
  41.  *            University of Illinois
  42.  *
  43.  *             All rights reserved
  44.  *
  45.  *
  46.  * NAME:
  47.  *    dump_line
  48.  *
  49.  * FUNCTION:
  50.  *    Does the actual printing of the stored up line
  51.  *
  52.  * ALGORITHM:
  53.  *    For each of the label, code, and comment sections which are used on 
  54.  *    this line:
  55.  *
  56.  *    1) Use pad_output to get the section aligned properly.
  57.  *    2) write the section
  58.  *
  59.  *    The indentation level used for the code is set by ps.ind_level.  After
  60.  *    printing, ps.ind_level is set to ps.i_l_follow.
  61.  *
  62.  *    An extra level of indentation is added if ps.ind_stmt is 1.  After 
  63.  *    printing, ps.ind_stmt is set to 1 iff the line just printed has an
  64.  *    unterminated, non-declaration statement.
  65.  *
  66.  * HISTORY:
  67.  *    initial coding     November 1976    D A Willcox of CAC
  68.  *
  69.  */
  70. #include "indent_globs.h"
  71.  
  72.  
  73.  
  74. int         ff = 014;        /* used to write a form feed */
  75. int         comment_open;
  76. static      paren_target;
  77.  
  78. dump_line()
  79. {                /* dump_line is the routine that actually
  80.                  * effects the printing of the new source.
  81.                  * It prints the label section, followed
  82.                  * by the code section with the
  83.                  * appropriate nesting level, followed by
  84.                  * any comments */
  85.     register int cur_col,
  86.                 temp_col,
  87.                 target_col;
  88.  
  89.     if (ps.procname[0]) {
  90.     if (troff)
  91.         fprintf(output, ".Pr \"%s\"\n", ps.procname);
  92.     ps.ind_level = 0;
  93.     ps.procname[0] = 0;
  94.     }
  95.     if (s_code == e_code && s_lab == e_lab && s_com == e_com) {
  96.     if (suppress_blanklines>0) suppress_blanklines--;
  97.     else {
  98.     ps.bl_line = true;
  99.     n_real_blanklines++;
  100.     }
  101.     }
  102.     else if (!inhibit_formatting) {
  103.     suppress_blanklines = 0;
  104.     ps.bl_line = false;
  105.     if (prefix_blankline_requested)
  106.         if (swallow_optional_blanklines) {
  107.         if (n_real_blanklines == 1)
  108.             n_real_blanklines = 0;
  109.         }
  110.         else {
  111.         if (n_real_blanklines == 0)
  112.             n_real_blanklines = 1;
  113.         }
  114.     while (--n_real_blanklines >= 0)
  115.         putc('\n', output);
  116.     n_real_blanklines = 0;
  117.     if (ps.ind_level == 0)
  118.         ps.ind_stmt = 0;    /* this is a class A kludge. dont do
  119.                  * additional statement indentation if we
  120.                  * are at bracket level 0 */
  121.  
  122.     if (e_lab != s_lab || e_code != s_code)
  123.         ++code_lines;    /* keep count of lines with code */
  124.  
  125.  
  126.     if (e_lab != s_lab) {    /* print lab, if any */
  127.         if (comment_open) {
  128.         comment_open = 0;
  129.         fprintf(output, ".*/\n");
  130.         }
  131.         while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
  132.         e_lab--;
  133.         cur_col = pad_output(1, compute_label_target());
  134.         fprintf(output, "%.*s", e_lab - s_lab, s_lab);
  135.         cur_col = count_spaces(cur_col, s_lab);
  136.     }
  137.     else
  138.         cur_col = 1;    /* there is no label section */
  139.  
  140.     ps.pcase = false;
  141.  
  142.     if (s_code != e_code) {    /* print code section, if any */
  143.         register char *p;
  144.  
  145.         if (comment_open) {
  146.         comment_open = 0;
  147.         fprintf(output, ".*/\n");
  148.         }
  149.         target_col = compute_code_target();
  150.         {
  151.         register    i;
  152.  
  153.         for (i = 0; i < ps.p_l_follow; i++)
  154.             if (ps.paren_indents[i] >= 0)
  155.             ps.paren_indents[i] = -(ps.paren_indents[i] + target_col);
  156.         }
  157.         cur_col = pad_output(cur_col, target_col);
  158.         for (p = s_code; p < e_code; p++)
  159.         if (*p == (char)0200)
  160.             fprintf(output, "%d", target_col * 7);
  161.         else
  162.             putc(*p, output);
  163.         cur_col = count_spaces(cur_col, s_code);
  164.     }
  165.     if (s_com != e_com)
  166.         if (troff) {
  167.         register char *p;
  168.  
  169.         if (e_com[-1] == '/' && e_com[-2] == '*')
  170.             e_com -= 2;
  171.         while (e_com > s_com && e_com[-1] == ' ')
  172.             e_com--;
  173.         *e_com = 0;
  174.         p = s_com;
  175.         while (*p == ' ')
  176.             p++;
  177.         if (p[0] == '/' && p[1] == '*')
  178.             p += 2;
  179.         else if (p[0] == '*')
  180.             p += p[1] == '/' ? 2 : 1;
  181.         while (*p == ' ')
  182.             p++;
  183.         if (*p == 0)
  184.             goto inhibit_newline;
  185.         if (!comment_open) {
  186.             if ('a' <= *p && *p <= 'z')
  187.             *p = *p + 'A' - 'a';
  188.             if (s_code != e_code || s_lab != e_lab) {
  189.             fprintf(output, "\\c\n./* %dp 1 %dp\n",
  190.                 ps.com_col * 7, target_col * 7);
  191.             }
  192.             else
  193.             fprintf(output, "./* %dp 0 %dp\n",
  194.                 ps.com_col * 7, target_col * 7);
  195.         }
  196.         comment_open = 1;
  197.         while (*p) {
  198.             if (*p == BACKSLASH)
  199.             putc(BACKSLASH, output);
  200.             putc(*p++, output);
  201.         }
  202.         }
  203.         else {        /* print comment, if any */
  204.         register    target = ps.com_col;
  205.         register char *com_st = s_com;
  206.  
  207.         target += ps.comment_delta;
  208.         while (target <= 0)
  209.             if (*s_com == ' ')
  210.             target++, s_com++;
  211.             else if (*s_com == '\t')
  212.             target = ((target - 1) & ~7) + 9, s_com++;
  213.             else
  214.             target = 1;
  215.         if (cur_col > target) {    /* if comment cant fit on this
  216.                      * line, put it on next line */
  217.             putc('\n', output);
  218.             cur_col = 1;
  219.             ++ps.out_lines;
  220.         }
  221.         cur_col = pad_output(cur_col, target);
  222.         if (!ps.box_com) {
  223.             if (star_comment_cont && com_st[1] != '*')
  224.             if (com_st[1] == ' ' && com_st[0] == ' ')
  225.                 com_st[1] = '*';
  226.             else
  227.                 fwrite(" * ", com_st[0] == '\t' ? 2 : com_st[0] == '*' ? 1 : 3, 1, output);
  228.         }
  229.         fwrite(com_st, e_com - com_st, 1, output);
  230.         ps.comment_delta = ps.n_comment_delta;
  231.         cur_col = count_spaces(cur_col, com_st);
  232.         ++ps.com_lines;    /* count lines with comments */
  233.         }
  234.     if (ps.use_ff)
  235.         putc('\014', output);
  236.     else
  237.         putc('\n', output);
  238. inhibit_newline:
  239.     ++ps.out_lines;
  240.     if (ps.just_saw_decl == 1 && blanklines_after_declarations) {
  241.         prefix_blankline_requested = 1;
  242.         ps.just_saw_decl = 0;
  243.     }
  244.     else
  245.         prefix_blankline_requested = postfix_blankline_requested;
  246.     postfix_blankline_requested = 0;
  247.     }
  248.     ps.decl_on_line = ps.in_decl;    /* if we are in the middle of a
  249.                      * declaration, remember that fact
  250.                      * for proper comment indentation */
  251.     ps.ind_stmt = ps.in_stmt & ~ps.in_decl;    /* next line should be
  252.                          * indented if we have not
  253.                          * completed this stmt and
  254.                          * if we are not in the
  255.                          * middle of a declaration */
  256.     ps.use_ff = false;
  257.     ps.dumped_decl_indent = 0;
  258.     *(e_lab = s_lab) = '\0';    /* reset buffers */
  259.     *(e_code = s_code) = '\0';
  260.     *(e_com = s_com) = '\0';
  261.     ps.ind_level = ps.i_l_follow;
  262.     ps.paren_level = ps.p_l_follow;
  263.     paren_target = -ps.paren_indents[ps.paren_level - 1];
  264.     return;
  265. };
  266.  
  267. compute_code_target() {
  268.     register    target_col = ps.ind_size * ps.ind_level + 1;
  269.  
  270.     if (ps.paren_level)
  271.     if (!lineup_to_parens)
  272.         target_col += continuation_indent * ps.paren_level;
  273.     else {
  274.         register    w;
  275.         register    t = paren_target;
  276.  
  277.         if ((w = count_spaces(t, s_code) - max_col) > 0
  278.         && count_spaces(target_col, s_code) <= max_col) {
  279.         t -= w + 1;
  280.         if (t > target_col)
  281.             target_col = t;
  282.         }
  283.         else
  284.         target_col = t;
  285.     }
  286.     else if (ps.ind_stmt)
  287.     target_col += continuation_indent;
  288.     return target_col;
  289. }
  290.  
  291. compute_label_target()
  292. {
  293.     return
  294.     ps.pcase ? (int) (case_ind * ps.ind_size) +1
  295.     : *s_lab == '#' ? 1
  296.     : ps.ind_size * (ps.ind_level - label_offset) +1;
  297. }
  298.  
  299.  
  300. /*
  301.  * Copyright (C) 1976 by the Board of Trustees of the University of
  302.  * Illinois 
  303.  *
  304.  * All rights reserved 
  305.  *
  306.  *
  307.  * NAME: fill_buffer 
  308.  *
  309.  * FUNCTION: Reads one block of input into input_buffer 
  310.  *
  311.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 1/7/77
  312.  * A Willcox of CAC    Added check for switch back to partly full input
  313.  * buffer from temporary buffer 
  314.  *
  315.  */
  316. int
  317. fill_buffer()
  318. {                /* this routine reads stuff from the input */
  319.     int         count;
  320.     register char *p;
  321.     register int i;
  322.     register FILE *f = input;
  323.  
  324.     if (bp_save != 0) {        /* there is a partly filled input buffer
  325.                  * left */
  326.     buf_ptr = bp_save;    /* dont read anything, just switch buffers */
  327.     buf_end = be_save;
  328.     bp_save = be_save = 0;
  329.     if (buf_ptr < buf_end)
  330.         return;        /* only return if there is really
  331.                  * something in this buffer */
  332.     }
  333.     p = in_buffer;
  334.     buf_ptr = p;
  335.     while ((*p++ = i = getc(f)) != EOF && i != '\n');
  336.     if (i == EOF) {
  337.     p[-1] = ' ';
  338.     *p++ = '\n';
  339.     had_eof = true;
  340.     }
  341.     buf_end = p;
  342.     if (p[-2] == '/' && p[-3] == '*') {
  343.     if (in_buffer[3] == 'I' && strncmp(in_buffer, "/**INDENT**", 11) == 0)
  344.         fill_buffer();    /* flush indent error message */
  345.     else {
  346.         int         com = 0;
  347.  
  348.         p = in_buffer;
  349.         while (*p == ' ' || *p == '\t')
  350.         p++;
  351.         if (*p == '/' && p[1] == '*') {
  352.         p += 2;
  353.         while (*p == ' ' || *p == '\t')
  354.             p++;
  355.         if (p[0] == 'I' && p[1] == 'N' && p[2] == 'D' && p[3] == 'E'
  356.             && p[4] == 'N' && p[5] == 'T') {
  357.             p += 6;
  358.             while (*p == ' ' || *p == '\t')
  359.             p++;
  360.             if (*p == '*')
  361.             com = 1;
  362.             else if (*p == 'O')
  363.             if (*++p == 'N')
  364.                 p++, com = 1;
  365.             else if (*p == 'F' && *++p == 'F')
  366.                 p++, com = 2;
  367.             while (*p == ' ' || *p == '\t')
  368.             p++;
  369.             if (p[0] == '*' && p[1] == '/' && p[2] == '\n' && com) {
  370.             if (s_com != e_com || s_lab != e_lab || s_code != e_code)
  371.                 dump_line();
  372.             if (!(inhibit_formatting = com - 1)) {
  373.                 n_real_blanklines = 0;
  374.                 postfix_blankline_requested = 0;
  375.                 prefix_blankline_requested = 0;
  376.                 suppress_blanklines = 1;
  377.             }
  378.             }
  379.         }
  380.         }
  381.     }
  382.     }
  383.     if (inhibit_formatting) {
  384.     p = in_buffer;
  385.     do
  386.         putc(*p, output);
  387.     while (*p++ != '\n');
  388.     }
  389.     return;
  390. };
  391.  
  392. /*
  393.  * Copyright (C) 1976 by the Board of Trustees of the University of
  394.  * Illinois 
  395.  *
  396.  * All rights reserved 
  397.  *
  398.  *
  399.  * NAME: pad_output 
  400.  *
  401.  * FUNCTION: Writes tabs and spaces to move the current column up to the
  402.  * desired position. 
  403.  *
  404.  * ALGORITHM: Put tabs and/or blanks into pobuf, then write pobuf. 
  405.  *
  406.  * PARAMETERS: current        integer        The current column target
  407.  * nteger        The desired column 
  408.  *
  409.  * RETURNS: Integer value of the new column.  (If current >= target, no
  410.  * action is taken, and current is returned. 
  411.  *
  412.  * GLOBALS: None 
  413.  *
  414.  * CALLS: write (sys) 
  415.  *
  416.  * CALLED BY: dump_line 
  417.  *
  418.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 
  419.  *
  420.  */
  421. pad_output(current, target)    /* writes tabs and blanks (if necessary)
  422.                  * to get the current output position up
  423.                  * to the target column */
  424.     int         current;    /* the current column value */
  425.     int         target;        /* position we want it at */
  426. {
  427.     register int curr;        /* internal column pointer */
  428.     register int tcur;
  429.  
  430.     if (troff)
  431.     fprintf(output, "\\h'|%dp'", (target - 1) * 7);
  432.     else {
  433.     if (current >= target)
  434.         return (current);    /* line is already long enough */
  435.     curr = current;
  436.     while ((tcur = ((curr - 1) & tabmask) + tabsize + 1) <= target) {
  437.         putc('\t', output);
  438.         curr = tcur;
  439.     }
  440.     while (curr++ < target)
  441.         putc(' ', output);    /* pad with final blanks */
  442.     }
  443.     return (target);
  444. };
  445.  
  446. /*
  447.  * Copyright (C) 1976 by the Board of Trustees of the University of
  448.  * Illinois 
  449.  *
  450.  * All rights reserved 
  451.  *
  452.  *
  453.  * NAME: count_spaces 
  454.  *
  455.  * FUNCTION: Find out where printing of a given string will leave the current
  456.  * character position on output. 
  457.  *
  458.  * ALGORITHM: Run thru input string and add appropriate values to current
  459.  * position. 
  460.  *
  461.  * RETURNS: Integer value of position after printing "buffer" starting in
  462.  * column "current". 
  463.  *
  464.  * HISTORY: initial coding     November 1976    D A Willcox of CAC 
  465.  *
  466.  */
  467. int
  468. count_spaces(current, buffer)
  469.  
  470. /*
  471.  * this routine figures out where the character position will be after
  472.  * printing the text in buffer starting at column "current" 
  473.  */
  474.     int         current;
  475.     char       *buffer;
  476. {
  477.     register char *buf;        /* used to look thru buffer */
  478.     register int cur;        /* current character counter */
  479.  
  480.     cur = current;
  481.  
  482.     for (buf = buffer; *buf != '\0'; ++buf) {
  483.     switch (*buf) {
  484.  
  485.         case '\n':
  486.         case 014:        /* form feed */
  487.         cur = 1;
  488.         break;
  489.  
  490.         case '\t':
  491.         cur = ((cur - 1) & tabmask) + tabsize + 1;
  492.         break;
  493.  
  494.         case '':        /* this is a backspace */
  495.         --cur;
  496.         break;
  497.  
  498.         default:
  499.         ++cur;
  500.         break;
  501.     }            /* end of switch */
  502.     }                /* end of for loop */
  503.     return (cur);
  504. };
  505.  
  506. int    found_err;
  507. diag(level, msg, a, b)
  508. {
  509.     if (level)
  510.     found_err = 1;
  511.     if (output == stdout) {
  512.     fprintf(stdout, "/**INDENT** %s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  513.     fprintf(stdout, msg, a, b);
  514.     fprintf(stdout, " */\n");
  515.     }
  516.     else {
  517.     fprintf(stderr, "%s@%d: ", level == 0 ? "Warning" : "Error", line_no);
  518.     fprintf(stderr, msg, a, b);
  519.     fprintf(stderr, "\n");
  520.     }
  521. }
  522.